﻿using Api.Core.IRepository;
using Api.Core.IRepository.IUnitOfWork;
using Api.Core.Model;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Api.Core.Repository
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        private ISugarUnitOfWork _db;

        public BaseRepository(ISugarUnitOfWork sugarUnitOfWork)
        {
            _db = sugarUnitOfWork;
            //  _db = sugarUnitOfWork.GetDbClient();
        }

        public async Task<int> Add(TEntity entity)
        {
            using (var context = _db.GetDbClient())
            {
                var insert = context.Insertable(entity);
                return await insert.ExecuteReturnIdentityAsync();
            }

        }

        public async Task<bool> Update(TEntity entity)
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Updateable(entity).ExecuteCommandHasChangeAsync();
            }

        }
        public async Task<bool> DeleteByIds(int[] ids)
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Deleteable<TEntity>().In(ids).ExecuteCommandHasChangeAsync();
            }
        }
        public async Task<bool> DeleteById(object id)
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Deleteable<TEntity>(id).ExecuteCommandHasChangeAsync();
            }

        }

        public async Task<List<TEntity>> Query()
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Queryable<TEntity>().ToListAsync();
            }

        }

        public async Task<int> Add(List<TEntity> listEntity)
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Insertable(listEntity.ToArray()).ExecuteCommandAsync();
            }
        }
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression)
        {
            using (var context = _db.GetDbClient())
            {
                return await context.Queryable<TEntity>().WhereIF(whereExpression != null, whereExpression).ToListAsync();
            }

        }


        public async Task<PageModel<TEntity>> QueryPage(
            Expression<Func<TEntity, bool>> whereExpression,
            int intPageIndex = 1,
            int intPageSize = 20,
            string strOrderByFileds = null)
        {
            using (var context = _db.GetDbClient())
            {
                RefAsync<int> totalCount = 0;
                var list = await context.Queryable<TEntity>()
                 .OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds)
                 .WhereIF(whereExpression != null, whereExpression)
                 .ToPageListAsync(intPageIndex, intPageSize, totalCount);

                int pageCount = (Math.Ceiling(totalCount.ObjToDecimal() / intPageSize.ObjToDecimal())).ObjToInt();
                return new PageModel<TEntity>() { dataCount = totalCount, pageCount = pageCount, page = intPageIndex, PageSize = intPageSize, Children = list };
            }

        }

        public async Task<PageModel<TResult>> QueryMuch<T, T2, T3, TResult>(
           int intPageIndex,
           int intPageSize,
           string strOrderByFileds,
           string where,
           Expression<Func<T, T2, T3, object[]>> joinExpression,
           Expression<Func<T, T2, T3, TResult>> selectExpression

           ) where T : class, new()
        {
            using (var context = _db.GetDbClient())
            {
                RefAsync<int> totalCount = 0;
                var list = await context.Queryable(joinExpression)
                .OrderByIF(!string.IsNullOrWhiteSpace(strOrderByFileds), strOrderByFileds)
                .WhereIF(!string.IsNullOrWhiteSpace(where), where)
                .Select(selectExpression)
                .ToPageListAsync(intPageIndex, intPageSize, totalCount);

                int pageCount = (Math.Ceiling(totalCount.ObjToDecimal() / intPageSize.ObjToDecimal())).ObjToInt();
                return new PageModel<TResult>() { dataCount = totalCount, pageCount = pageCount, page = intPageIndex, PageSize = intPageSize, Children = list };
            }

        }


    }
}
